package org.sdnstproject.interlayer.DummyProxyV10;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

import org.projectfloodlight.openflow.exceptions.OFParseError;
import org.projectfloodlight.openflow.protocol.OFFactories;
import org.projectfloodlight.openflow.protocol.OFHello;
import org.projectfloodlight.openflow.protocol.OFMessage;
import org.projectfloodlight.openflow.protocol.OFMessageReader;
import org.projectfloodlight.openflow.protocol.OFType;
import org.sdnstproject.interlayer.interlayerProxy.Configuration;
import org.sdnstproject.interlayer.DummyProxyV13.ListenV13;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

public class ListenV10 extends Thread{
    private static final Logger log = LoggerFactory.getLogger(ListenV13.class);
    private Configuration config = Configuration.getInstance();
    private int port = Integer.parseInt(config.getInterlayerPort());
    public ServerSocket serverSock;
    public volatile boolean running = true;
    public InputStream in;
    public OutputStream out;
    private DummyControllerV10 ofController;
    private OFMessageReader<OFMessage> reader = OFFactories.getGenericReader();
    public volatile boolean first = true;

    public ListenV10(DummyControllerV10 ofController) {
        this.ofController = ofController;
    }
    public void getServerSocket() throws IOException {
        log.info("[DummyController] Listening switches on " + port);
        serverSock = new ServerSocket(port);
        serverSock.setReuseAddress(true);
    }
    @Override
    public void run() {
        try {
            log.info("[DummyController] Listening switches on " + port);
            serverSock = new ServerSocket(port);
            serverSock.setReuseAddress(true);
        } catch (IOException e1) {
            running = false;
            e1.printStackTrace();
        }
        try {
            while(running && !Thread.currentThread().isInterrupted()) {
                Socket tempSocket = null;
                tempSocket = serverSock.accept();
                log.info("[DummyController] Switch connected from  " + tempSocket.toString());
                in = tempSocket.getInputStream();
                out = tempSocket.getOutputStream();

                byte[] temprecv = new byte[32];
                try {
                    while (first && in.read(temprecv, 0, temprecv.length) != -1) {
                        log.info("first get a massage.");
                        if(temprecv[1] == (byte)0) {
                            ByteBuf bb = Unpooled.copiedBuffer(temprecv);
                            OFMessage message;
                            try {
                                message = reader.readFrom(bb);
                            } catch (OFParseError e) {
                                log.info(e.toString());
                                continue;
                            }
                            if(message.getType() == OFType.HELLO) {
                                log.info(message.toString());
                                ofController.targetSock = tempSocket;
                                ofController.in = in;
                                ofController.out = out;
//								ofController.state.processOFMsg(message);
                                ofController.state.processOFHello((OFHello)message);
                                ofController.start();
                                log.info("ofController start.");
                                first = false;
                                break;
                            }
                            bb.clear();
                        }
                    }
                } catch (Exception e) {
                    log.info(e.toString());
                    continue;
                }
            }
        } catch (SocketException e) {
            log.info(e.toString());
        }catch (Exception e) {
            e.printStackTrace();
        }finally {
            try {
                if(serverSock != null) serverSock.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

